mod middlewares;
mod utils;

use chrono::NaiveDateTime;

pub use middlewares::*;
use serde::{Deserialize, Serialize};
use sqlx::prelude::FromRow;
pub use utils::*;
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, ToSchema, Deserialize, FromRow, PartialEq)]
pub struct User {
    pub id: i64,
    pub fullname: String,
    pub email: String,
    pub ws_id: i64,
    #[sqlx(default)]
    pub password_hash: Option<String>,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub updated_date: NaiveDateTime,
    pub updated_name: String,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub created_date: NaiveDateTime,
    pub created_name: String,
}
// create struct Messages
#[derive(Debug, Clone, ToSchema, Serialize, Deserialize, FromRow, PartialEq)]
pub struct Messages {
    pub id: i64,
    pub chat_id: i64,
    pub sender_id: i64,
    pub content: String,
    pub files: Vec<String>,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub updated_date: NaiveDateTime,
    pub updated_name: String,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub created_date: NaiveDateTime,
    pub created_name: String,
}
#[derive(Debug, Clone, Serialize, PartialEq, PartialOrd, ToSchema, Deserialize, sqlx::Type)]
#[sqlx(type_name = "chat_type", rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum ChatType {
    Single,
    Group,
    PrivateChannel,
    PublicChannel,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, FromRow, PartialEq)]
pub struct Chat {
    pub id: i64,
    pub ws_id: i64,
    pub name: Option<String>,
    pub r#type: ChatType,
    pub members: Vec<i64>,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub updated_date: NaiveDateTime,
    pub updated_name: String,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub created_date: NaiveDateTime,
    pub created_name: String,
}

#[derive(Debug, Clone, Serialize, ToSchema, Deserialize, PartialEq, FromRow)]
pub struct Workspace {
    pub id: i64,
    pub name: String,
    pub owner_id: i64,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub updated_date: NaiveDateTime,
    pub updated_name: String,
    #[serde(skip_serializing)]
    #[serde(skip_deserializing)]
    pub created_date: NaiveDateTime,
    pub created_name: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, FromRow, PartialEq)]
pub struct ChatUser {
    pub id: i64,
    pub fullname: String,
    pub email: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateWorkspace {
    pub name: String,
}
#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
pub struct SignupUser {
    pub fullname: String,
    pub email: String,
    pub ws_name: String,
    pub password: String,
}
#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
pub struct CreateUser {
    pub fullname: String,
    pub email: String,
    pub ws_id: i64,
    pub password: String,
}

#[derive(Debug, Clone, Serialize, ToSchema, Deserialize)]
pub struct SigninUser {
    pub email: String,
    pub password: String,
}
#[cfg(test)]
impl User {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        id: i64,
        fullname: String,
        email: String,
        password_hash: Option<String>,
        updated_date: chrono::NaiveDateTime,
        updated_name: String,
        created_date: chrono::NaiveDateTime,
        created_name: String,
    ) -> Self {
        let ws_id: i64 = 1;
        Self {
            id,
            fullname,
            email,
            ws_id,
            password_hash,
            updated_date,
            updated_name,
            created_date,
            created_name,
        }
    }
}

#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
pub struct ListMessages {
    pub page_index: i64,
    pub page_size: i64,
    pub last_id: i64,
}

#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
pub struct CreateMessages {
    pub content: String,
    pub files: Vec<String>,
}

#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
pub struct PageInstanceVO<T> {
    pub total: i64,
    pub list: Vec<T>,
}

impl<T> PageInstanceVO<T> {
    pub fn new(total: i64, list: Vec<T>) -> Self {
        Self { total, list }
    }
    pub fn empty() -> Self {
        Self {
            total: 0,
            list: vec![],
        }
    }
}

impl CreateMessages {
    pub fn new(content: String, files: Vec<String>) -> Self {
        Self { content, files }
    }
}

impl CreateWorkspace {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl SignupUser {
    pub fn new(fullname: String, email: String, ws_name: String, password: String) -> Self {
        Self {
            fullname,
            email,
            ws_name,
            password,
        }
    }
}

impl SigninUser {
    pub fn new(email: String, password: String) -> Self {
        Self { email, password }
    }
}

impl CreateUser {
    pub fn new(fullname: String, email: String, ws_id: i64, password: String) -> Self {
        Self {
            fullname,
            email,
            ws_id,
            password,
        }
    }
}
